package com.pennphoto.client;




import java.sql.Date;
import java.util.ArrayList;
import java.util.HashMap;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.HistoryListener;
import com.google.gwt.dom.client.Style.Unit;
import com.pennphoto.server.QueryEngine;
/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class UserProfile implements EntryPoint, HistoryListener {
	/**
	 * The message displayed to the user when the server cannot be reached or
	 * returns an error.
	 */
	private static final String SERVER_ERROR = "An error occurred while "
			+ "attempting to contact the server. Please check your network "
			+ "connection and try again.";
	private DialogBox dialogBox;
	private Button closeButton;
	final QueryServiceAsync engine = GWT.create(QueryService.class);
	/**
	 * Create a remote service proxy to talk to the server-side Greeting service.
	 */
	//private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
	private int userid;
	private HTMLPanel panel;
	public static final String INIT_STATE="initstate";
	final Label textToServerLabel = new Label();
	final HTML serverResponseLabel = new HTML();
	/*private DockPanel dockPanel;
	private FlowPanel flowPanel_2;
	private FlowPanel flowPanel;
	
	AbsolutePanel absolutePanel;*/
	FlowPanel htmlUserUpdates;
	RootPanel rootPanel;
	//constructor
	public UserProfile(int uid){
		userid=uid;
		panel= new HTMLPanel("");
		this.initHistorySupport();
		rootPanel = RootPanel.get();
		
		
		}
	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		final Label errorLabel = new Label();
		
		// Add the nameField and sendButton to the RootPanel
		// Use RootPanel.get() to get the entire body element
		rootPanel = RootPanel.get();
		rootPanel.setSize("100%", "100%");
		final Grid grid = new Grid();
		//rootPanel.setSize("900px", "600px");
		//RootPanel.get("errorLabelContainer").add(errorLabel);
		VerticalPanel verticalPanel = new VerticalPanel();
		rootPanel.add(verticalPanel, 46, 30);
		verticalPanel.setSize("90%", "90%");
		
		MenuBar menuBar = new MenuBar(false);
		verticalPanel.add(menuBar);
		menuBar.setWidth("100%");
		
		MenuItem mntmHome = new MenuItem("Home", false, new Command() {
			public void execute() {
				RootPanel.get().clear();
				
				onModuleLoad();
			}
		});
		menuBar.addItem(mntmHome);
		
		MenuItem mntmProfile = new MenuItem("Profile", false, new Command() {
			public void execute() {
				try {
					
					htmlUserUpdates.clear();	
					htmlUserUpdates.remove(panel);
					htmlUserUpdates.add(getUserProfilePanelForId(userid));
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					displayError(e.getMessage());
				}
			}
		});
		menuBar.addItem(mntmProfile);
		
		MenuItem mntmPhotos = new MenuItem("Photos", false, new Command() {
			public void execute() {
				rootPanel.get().clear();
				PhotoRegisterView p = new PhotoRegisterView(userid);
				p.onModuleLoad();
			}
		});
		menuBar.addItem(mntmPhotos);
		MenuBar menuBar_1 = new MenuBar(true);
		
		MenuItem mntmFriends_1 = new MenuItem("Friends", false, menuBar_1);
		
		MenuItem mntmFriendshipBrowser = new MenuItem("Friendship Browser", false, new Command() {
			public void execute() {
				rootPanel.get().clear();
				PennPhoto p = new PennPhoto(userid);
				p.onModuleLoad();
			}
		});
		menuBar_1.addItem(mntmFriendshipBrowser);
		menuBar.addItem(mntmFriends_1);
		
		MenuItem mntmCircles = new MenuItem("Circles", false, new Command() {
			public void execute() {
				try {			
					final FlexTable circles = new FlexTable();
						engine.getCircles(userid, new AsyncCallback<Circles> (){
						public void onFailure(Throwable caught) {
							// Show the RPC error message to the user
							caught.printStackTrace();
							displayError(caught.getMessage());
						}

						public void onSuccess(Circles result) {
								int i=0;
								int j =0;
								HashMap<String,HashMap<Integer,String>> hm = new HashMap<String,HashMap<Integer,String>>();
								
								hm=result.getFriends();
								for(final String circleName:hm.keySet()){
									Label cirName = new Label("You have in "+circleName +":");
									
									circles.setWidget(i+j, 0, cirName);
									i++;
									
									for(final int id:hm.get(circleName).keySet()){
										final Hyperlink commenterLink = new Hyperlink(hm.get(circleName).get(id), ""+id);
										
										final Button remove = new Button("X");
										remove.setSize("30px", "30px");
										
										//remove
										circles.setWidget(j+i,1,commenterLink);
										circles.setWidget(j+i,2,remove);
										j++;
										remove.addClickHandler(new ClickHandler(){

											@Override
											public void onClick(ClickEvent event) {
												// TODO Auto-generated method stub
												engine.removeFriend(userid, id, circleName, new AsyncCallback<String>(){

													@Override
													public void onFailure(Throwable caught) {
														displayError(caught.getMessage());
														
													}

													@Override
													public void onSuccess(String result){										
														// TODO Auto-generated method stub
													final DialogBox bd = new DialogBox();	
													if(result.equals("Success")){
															bd.setText("Successfully removed");
															circles.remove(commenterLink);
															circles.remove(remove);
														}
													else 
														bd.setText("Could not be removed");
													Button ok = new Button("Ok");
													bd.add(ok);
													ok.setFocus(true);
													ok.addClickHandler(new ClickHandler(){

														@Override
														public void onClick(
																ClickEvent event) {
															bd.hide();
															
														}
														
													});
													bd.center();
													
													}
													
												});
											}
											
										});
										
									}
									
									
								}
								
							}
					});
						htmlUserUpdates.remove(panel);
						htmlUserUpdates.add(circles);
						
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					displayError(e.getMessage());
				}
			}
		});
		menuBar.addItem(mntmCircles);
		
		final Button btnLogout = new Button("Logout");
		verticalPanel.add(btnLogout);
		verticalPanel.setCellHorizontalAlignment(btnLogout, HasHorizontalAlignment.ALIGN_RIGHT);
		
		DockPanel dockPanel = new DockPanel();
		verticalPanel.add(dockPanel);
		dockPanel.setSize("100%", "95%");
		
		AbsolutePanel absolutePanel = new AbsolutePanel();
		dockPanel.add(absolutePanel, DockPanel.NORTH);
		absolutePanel.setSize("100%", "114px");
		
		Image image = new Image("img/penn.jpg");
		absolutePanel.add(image, 10, 0);
		image.setSize("100px", "114px");
		
		HTML htmlpennphoto = new HTML("<h1>PennPhoto</h1>", true);
		absolutePanel.add(htmlpennphoto, 116, 0);
		htmlpennphoto.setSize("125px", "71px");
		
		Label lblSearchPennPhoto = new Label("Search Penn Photo for users:");
		absolutePanel.add(lblSearchPennPhoto, 268, 86);
		
		TextBox textBox = new TextBox();
		absolutePanel.add(textBox, 446, 74);
		textBox.setSize("252px", "18px");
		
		Button btnGo = new Button("Go!");
		absolutePanel.add(btnGo, 724, 74);
		
		FlowPanel flowPanel = new FlowPanel();
		dockPanel.add(flowPanel, DockPanel.WEST);
		
		final HTMLPanel htmlUserInformation = new HTMLPanel("User Information:");
		flowPanel.add(htmlUserInformation);
		htmlUserInformation.setHeight("187px");
		
		htmlUserUpdates = new FlowPanel();
		dockPanel.add(htmlUserUpdates, DockPanel.CENTER);
		htmlUserUpdates.setWidth("425px");
		
		panel = new HTMLPanel("Friend Updates:");
		htmlUserUpdates.add(panel);
		panel.setSize("517px", "248px");
		
		FlowPanel flowPanel_2 = new FlowPanel();
		dockPanel.add(flowPanel_2, DockPanel.EAST);
		
		HTML htmlFriendRecommendations = new HTML("Friend Recommendations:", true);
		flowPanel_2.add(htmlFriendRecommendations);
		htmlFriendRecommendations.setHeight("116px");
		
		final FlexTable frndTable = new FlexTable();
		flowPanel_2.add(frndTable);
		
		
		
		//friendgrd.setSize("77px", "83px");
		engine.getFriendRecommendation(userid, new AsyncCallback<HashMap<Integer,String>>(){

			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub
				caught.printStackTrace();
			}

			@Override
			public void onSuccess(HashMap<Integer, String> result) {
				
				// TODO Auto-generated method stub
				int i=1;
				
				for ( final int key: result.keySet()){
					final Hyperlink friendLink = new Hyperlink(result.get(key), ""+key);
					final Button accept = new Button("Accept");
					frndTable.setWidget(i, 0, friendLink);
					frndTable.setWidget(i,1, accept);
					//grid.setWidget(i,0,friendLink);
					//grid.setWidget(i,1,accept);
					i++;
					final ListBox lb = new ListBox();
					accept.addClickHandler( new ClickHandler(){
						
						@Override
						public void onClick(ClickEvent event) {
							// TODO Auto-generated method stub
							//grid.remove(friendLink);
							//grid.remove(accept);
							engine.getCircles(userid, new AsyncCallback<Circles>(){

								@Override
								public void onFailure(Throwable caught) {
									// TODO Auto-generated method stub
									caught.printStackTrace();
								}

								@Override
								public void onSuccess(Circles result) {
									HashMap<String,HashMap<Integer,String>> hm = new HashMap<String,HashMap<Integer,String>>();
									hm=result.getFriends();
									for(String circleName:hm.keySet()){
										lb.addItem(circleName);
									}
								}
								
							});
							final DialogBox db1 = new DialogBox();
							db1.addStyleName("Choose a circle"); 
							final FlexTable vp = new FlexTable();
							Label title=new Label("To which circle do you want to add");
							vp.setWidget(0,1,title);
							final TextBox name = new TextBox();
							name.setText("Enter circleName");
							vp.setWidget(1,1,friendLink);
							vp.setWidget(1,2,lb);
							Label newCircle=new Label("To Add to new circle");
							vp.setWidget(2,1,newCircle);
							vp.setWidget(2,2, name );
							Button Add = new Button("Add");
							Button cancel = new Button("Cancel");
							
							engine.getcircleRecommendation( userid, key, new AsyncCallback<String>(){

								@Override
								public void onFailure(Throwable caught) {
									// TODO Auto-generated method stub
									
								}

								@Override
								public void onSuccess(String result) {
									// TODO Auto-generated method stub
									Label circleReco = new Label();
									if (!result.equals("")){
									circleReco= new Label("Your can add him to " +result);
									}else{
										circleReco= new Label("You can add him to any circle");
									}
									vp.setWidget(3,1,circleReco);
								}
								
							});
							db1.setText("Choose a circle");
							vp.setWidget(4,1,Add);
							vp.setWidget(4,2,cancel);
							db1.add(vp);
							Add.setFocus(true);
							db1.center();
							
							Add.addClickHandler(new ClickHandler(){

								@Override
								public void onClick(ClickEvent event) {
									//(lb.getItemText(lb.getSelectedIndex()));
									if (!name.getText().equals("Enter circleName")){
										engine.addToCircle(userid, key, name.getText().toString(), new AsyncCallback<String>(){

											@Override
											public void onFailure(Throwable caught) {
												caught.printStackTrace();
											}

											public void onSuccess(String result) {
												final DialogBox db =new DialogBox();
												VerticalPanel vp = new VerticalPanel();
												vp.add(new Label("    "+result+"    "));
												Button ok = new Button("Ok");
												vp.add(ok);
												db.add(vp);
												ok.setFocus(true);
												ok.addClickHandler(new ClickHandler(){

													@Override
													public void onClick(
															ClickEvent event) {
														db.hide();
														
													}
													
												});
												db.center();
											}
											
										});

										db1.hide();
										
									}
									
									else{
									engine.addToCircle(userid, key, (lb.getItemText(lb.getSelectedIndex())).toString(), new AsyncCallback<String>(){

										@Override
										public void onFailure(Throwable caught) {
											caught.printStackTrace();
										}

										public void onSuccess(String result) {
											final DialogBox db =new DialogBox();
											VerticalPanel vp = new VerticalPanel();
											vp.add(new Label(result));
											Button ok = new Button("Ok");
											vp.add(ok);
											db.add(vp);
											ok.setFocus(true);
											ok.addClickHandler(new ClickHandler(){

												@Override
												public void onClick(
														ClickEvent event) {
													db.hide();
													
												}
												
											});
											db.center();
										}
										
									});

									db1.hide();
									
								}
								}	
							});
							cancel.addClickHandler(new ClickHandler(){

								@Override
								public void onClick(ClickEvent event) {
									db1.hide();
									
								}
								
							});
							
							frndTable.remove(accept);
							
							
						}
						
					});
				}
			}
			
		});
		
		HTML html = new HTML("<center>Copyright Penn 2011 All rights reserved.</center>", true);
		verticalPanel.add(html);
		verticalPanel.setCellVerticalAlignment(html, HasVerticalAlignment.ALIGN_BOTTOM);
		html.setWidth("100%");
		// Create the popup dialog box
		dialogBox = new DialogBox();
		dialogBox.setText("Remote Procedure Call");
		dialogBox.setAnimationEnabled(true);
		final Button closeButton = new Button("Close");
		// We can set the id of a widget by accessing its Element
		closeButton.getElement().setId("closeButton");
		
		VerticalPanel dialogVPanel = new VerticalPanel();
		dialogVPanel.addStyleName("dialogVPanel");
		dialogVPanel.add(new HTML("<b>Sending name to the server:</b>"));
		dialogVPanel.add(textToServerLabel);
		dialogVPanel.add(new HTML("<br><b>Server replies:</b>"));
		dialogVPanel.add(serverResponseLabel);
		dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
		dialogVPanel.add(closeButton);
		dialogBox.setWidget(dialogVPanel);

		// Add a handler to close the DialogBox
		closeButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				dialogBox.hide();
				///sendButton.setEnabled(true);
				//sendButton.setFocus(true);
			}
		});
		btnLogout.addClickHandler(new ClickHandler() {
			@SuppressWarnings("deprecation")
			public void onClick(ClickEvent e){
			rootPanel.get().clear();
			userid=0;	
			History.back();
			History.newItem("");
			
			History.removeHistoryListener(null);
			new Login().onModuleLoad();
			}});
		//profile load code:
		try {
			
			engine.getUserInformation(userid, new AsyncCallback<com.pennphoto.client.PersonType>() {
							public void onFailure(Throwable caught) {
								// Show the RPC error message to the user
								dialogBox
										.setText("Remote Procedure Call - Failure");
								serverResponseLabel
										.addStyleName("serverResponseLabelError");
								serverResponseLabel.setHTML(SERVER_ERROR+" "+caught.getMessage());
								dialogBox.center();
								closeButton.setFocus(true);
							}

							public void onSuccess(PersonType result) {
								
								dialogBox.setText("Remote Procedure Call");
								serverResponseLabel
										.removeStyleName("serverResponseLabelError");
								Integer uid = result.getUserId();
								VerticalPanel vp = new VerticalPanel();
								vp.add(new Hyperlink(result.getName(), uid.toString()));
								vp.add(new HTML("<table><tr><td>Email: "+result.getEmail()+"</td></tr><tr><td>Gender: "+result.getGender()+"</table>"));
								htmlUserInformation.add(vp);
								//htmlUserInformation.setHTML(result);
								//serverResponseLabel.setHTML(result);
								//dialogBox.center();
								//closeButton.setFocus(true);
							}
						});
			engine.getUserPhotos(userid, new AsyncCallback<ArrayList<ViewedPhotos>>() {
				public void onFailure(Throwable caught) {
					// Show the RPC error message to the user
					dialogBox
							.setText("Remote Procedure Call - Failure");
					serverResponseLabel
							.addStyleName("serverResponseLabelError");
					serverResponseLabel.setHTML(SERVER_ERROR+" "+caught.getMessage());
					dialogBox.center();
					closeButton.setFocus(true);
				}

				public void onSuccess(ArrayList<ViewedPhotos> result) {
					
					dialogBox.setText("Remote Procedure Call");
					serverResponseLabel.removeStyleName("serverResponseLabelError");
					panel.clear();
					for(ViewedPhotos v:result)
					{
						VerticalPanel vpanel = new VerticalPanel();
						Image img = new Image();
						img.setUrl(v.getUrl());
						img.setHeight("150px");
						img.setWidth("150px");
						vpanel.add(img);
						if(v.getViewers()!=null && v.getViewers().size()>0)
						{
							for(int i=0;i<v.getViewers().size();i++)
							{
								
								Hyperlink commenterLink = new Hyperlink(v.getViewers().get(i), v.getViewerids().get(i).toString());
								vpanel.add(commenterLink);
								InlineLabel lbl = new InlineLabel("" +v.getComments().get(i));
								vpanel.add(lbl);
							}
							//Button btn = new Button("Comment");
							//vpanel.add(btn);
							
						}
						else
						{
							InlineLabel lbl = new InlineLabel(v.getDesc());
							vpanel.add(lbl);
						}
						panel.add(vpanel);
					}
					
				}
			});
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			displayError(e.getMessage());
		}
	}	

	@SuppressWarnings("deprecation")
	public void initHistorySupport() {

		  // add the MainPanel as a history listener

		  History.addHistoryListener(this);
		  
		  
		  // check to see if there are any tokens passed at startup via the browser's URI

		  String token = History.getToken();
		  
		  if (token.length() == 0) {

		    onHistoryChanged(INIT_STATE);

		  }

		  else {

		    onHistoryChanged(token);

		  }

		}	

	/**

	 * this method is called when the MainPanel's contents must be changed due to a state change.

	 * in the context of this app, a state change represents a new URL being loaded for the RSS reader.

	 */

	public void updateState(String token) {

		if(token!=null && !token.isEmpty())
		{
	  if (token.equals(INIT_STATE)) {

	    //lbl.setText("There is no token passed in the browser URL");
		  //rootPanel.clear();
		  //new UserProfile(userid).
		  onModuleLoad();
	  }

	  else {

	    //lbl.setText("Got a new browser history change token:" + token);
		  try{
			
		  int uid = Integer.parseInt(token);
		 
		  if(uid!=userid)
		  {
			 panel.clear();
			 panel.add(getUserProfilePanelForId(uid));
			 
		  }else{
			  rootPanel.clear();
			  History.newItem(String.valueOf(userid));
			  onModuleLoad();
		  }
		  }catch(Exception e){
			  displayError(e.getMessage());
			  e.printStackTrace();
		  }
	  	} 
	  }	

	}

	/**

	 * this method is called when the fwd/back buttons are invoked on the browser.

	 * this is also invoked when hyperlinks (generated by the app) are clicked.

	 */
	public void displayError(String message)
	{
		dialogBox.setText("Remote Procedure Call - Failure");
		serverResponseLabel.addStyleName("serverResponseLabelError");
		serverResponseLabel.setHTML(SERVER_ERROR+": "+message);
		dialogBox.center();
		//closeButton.setFocus(true);
	}
	public void onHistoryChanged(String historyToken) {

	  // todo - when the token is passed, do something to update the state of your app

	  updateState(historyToken);

	}
				
	public VerticalPanel getUserProfilePanelForId(int uid) throws Exception
	{
		final VerticalPanel vpanel = new VerticalPanel();
		if(uid>0)
		{
			 engine.getUserInformation(uid, new AsyncCallback<com.pennphoto.client.PersonType>() {
				public void onFailure(Throwable caught) {
					// Show the RPC error message to the user
					dialogBox
							.setText("Remote Procedure Call - Failure");
					serverResponseLabel
							.addStyleName("serverResponseLabelError");
					serverResponseLabel.setHTML(SERVER_ERROR+" "+caught.getMessage());
					dialogBox.center();
					closeButton.setFocus(true);
				}

				public void onSuccess(PersonType person) 
				{
					Label name = new Label("Name: "+person.getName());
					Label email = new Label("Email: "+person.getEmail());
					Label gender = new Label("Gender: "+person.getGender());
					java.util.Date d= new java.util.Date();
					
					java.util.Date date = person.getDateofbirth();
					//long sum = d.getTime() + date.getTime();
					//Date sumDate = new Date(sum);
					//Label age = new Label("Age: "+sumDate);
					vpanel.add(name);
					vpanel.add(email);
					vpanel.add(gender);
					//vpanel.add(age);
				}
				});
				
			
			
		}
		return vpanel;
	}
		
	public static native String getParamString() /*-{

    return $wnd.location.search;

}-*/;

public static HashMap parseParamString(String string) {
	
	String[] ray = string.substring(1, string.length()).split("&");
	
	HashMap map = new HashMap();
	
	for (int i = 0; i < ray.length; i++) {
	
	GWT.log("ray[" + i + "]=" + ray[i], null);
	
	String[] substrRay = ray[i].split("=");
	
	map.put(substrRay[0], substrRay[1]);

	}

	return map;

	}
		
	
}
